﻿using Sustainalytics.Accounts.BusinessLogic;
using Sustainalytics.Accounts.Service.Models;
using Sustainalytics.AuthOperations;
using Sustainalytics.DataLayer.Exceptions.AccountsAndUsers;
using Sustainalytics.Entities;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.Accounts.Service.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/v1/users")]
    public class UsersController : ApiController
    {
        private readonly IAccountsManagement _accountsManagement;
        private readonly IAuthOperations _authOperations;

        public UsersController(IAccountsManagement accountsManagement, IAuthOperations authOperations)
        {
            _accountsManagement = accountsManagement;
            _authOperations = authOperations;
        }

        [Route("")]
        public HttpResponseMessage Get([FromUri]ListOptions filters, [FromUri]List<Guid> accountIds,
            string status = null, string name = "", bool returnAccounts = false, bool returnLastCrmSyncDate = false)
        {
            try
            {
                Entities.Status statusEnum;
                var nullableStatus = Enum.TryParse(status, out statusEnum) ? statusEnum : (Entities.Status?)null;
                string accountIdsString = "";
                if (accountIds != null && accountIds.Count > 0)
                    accountIdsString = string.Join(",", accountIds.ConvertAll<string>(x => x.ToString()));

                if (filters != null && filters.GetCount)
                {
                    int usersCount = 0;
                    try
                    {
                        usersCount = _accountsManagement.GetUsersTotalCount(accountIds, nullableStatus, name);
                    }
                    catch (Exception ex)
                    {
                        return Request.CreateResponse(HttpStatusCode.BadRequest, new { Code = ErrorCodes.ErrorRetrievingUsers });
                    }

                    return Request.CreateResponse(HttpStatusCode.OK, usersCount);
                }

                if (returnLastCrmSyncDate)
                {
                    string stringValue = "";
                    try
                    {
                        var lastCrymSyncDate = _accountsManagement.GetLastSyncDate(SyncType.User);
                        stringValue = lastCrymSyncDate.HasValue ? lastCrymSyncDate.Value.ToString(System.Globalization.CultureInfo.InvariantCulture) : "";
                    }
                    catch (Exception ex)
                    {
                        return Request.CreateResponse(HttpStatusCode.BadRequest, new { Code = ErrorCodes.ErrorRetrievingUsers });
                    }

                    return Request.CreateResponse(HttpStatusCode.OK, stringValue);
                }

                if (returnAccounts)
                {
                    List<object> accounts = new List<object>();
                    try
                    {
                        foreach (var account in _accountsManagement.GetAccountsByUserSatusAndSearchFilter(nullableStatus, name))
                        {
                            accounts.Add(AccountDto.CreateWithNameId(account));
                        }
                    }
                    catch (Exception ex)
                    {
                        return Request.CreateResponse(HttpStatusCode.BadRequest, new { Code = ErrorCodes.ErrorRetrievingUsers });
                    }

                    return Request.CreateResponse(HttpStatusCode.OK, accounts);
                }

                List<User> users = _accountsManagement.GetUsers(accountIds, nullableStatus, name, filters);
                List<object> userDtos = new List<object>();
                if (users != null)
                {
                    users.ForEach(u => userDtos.Add(UserDto.CreateIdFullNameEmailAccountAccessDateStatus(u)));
                }
                return Request.CreateResponse(System.Net.HttpStatusCode.OK, userDtos);
            }
            catch (UserNotFoundException ex)
            {
                string accountIdsString = string.Join(",", accountIds.ConvertAll<string>(x => x.ToString()));
                return Request.CreateResponse(HttpStatusCode.NotFound, new { Code = ErrorCodes.ErrorRetrievingUsers });
            }
            catch (Exception ex)
            {
                string accountIdsString = string.Join(",", accountIds.ConvertAll<string>(x => x.ToString()));
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { Code = ErrorCodes.ErrorRetrievingUsers });
            }
        }

        // [CacheOutput(ServerTimeSpan = 100, ClientTimeSpan = 0, NoCache = true, MustRevalidate = true, Private = true)]
        [Route("{userId}")]
        public HttpResponseMessage Get(Guid userId)
        {
            try
            {
                var user = _accountsManagement.GetUserByUserId(userId);
                var clientUser = _accountsManagement.GetClientUserByUserId(userId);

                return Request.CreateResponse(System.Net.HttpStatusCode.OK, UserDto.CreateComplete(user, clientUser.PasswordExpirationDate));
            }
            catch (UserNotFoundException ex)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound, new { Code = ErrorCodes.ErrorRetrievingSelectedUser });
            }
            catch (ClientUserNotFoundException ex)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound, new { Code = ErrorCodes.ErrorRetrievingSelectedUser });
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { Code = ErrorCodes.ErrorRetrievingSelectedUser });
            }
        }

        [Route("")]
        public HttpResponseMessage Patch(List<PatchOperations> operations)
        {
            string userIds = "";

            try
            {
                foreach (var op in operations)
                {
                    if (op.Verb.ToUpperInvariant().Trim() == "RESETPASSWORD")
                    {
                        _authOperations.ResetPasswordByUserIds(op.ResourceIds);
                    }
                }

                return Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (CustomException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { Code = ex.InternalCode });
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { Code = ErrorCodes.ErrorResetingPassword });
            }
        }
    }
}
